#pragma once

#include<unistd.h>
#include<string>
#include<cstdlib>
#include<iostream>
#include<sys/wait.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include"Log.hpp"
//#include"TcpServer.hpp"

#include<memory.h>
Log lg;
const int backlog=10;
enum{
    SockerErr=2,
    BindErr,
    ListenErr
};
//封装套接字接口
class Sock
{
public:
    Sock()
    {}
    ~Sock()
    {}

public:
    void Socket()
    {
        fd_=socket(AF_INET,SOCK_STREAM,0);
        if(fd_<0)
        {
            lg(Fatal,"sockfd_ error,%s:%d",strerror(errno),errno);
            exit(SockerErr);
        }

    }
    void Bind(uint16_t port)
    {
        struct sockaddr_in lock;
        memset(&lock,0,sizeof(lock));
        lock.sin_family=AF_INET;
        lock.sin_port=htons(port);
        lock.sin_addr.s_addr=INADDR_ANY;

        if(bind(fd_,(struct sockaddr*)& lock,sizeof(lock))<0)
        {
            lg(Fatal,"bind error,%s:%d",strerror(errno),errno);
            exit(BindErr);
        }
    }
    void Listen()//监听
    {
        if(listen(fd_,backlog)<0)
        {
            
            lg(Fatal,"bind error,%s:%d",strerror(errno),errno);
            exit(ListenErr);
        }
    }
    int Accept( std::string *clintip,std::uint16_t* clintport)//获取链接
    {
        struct sockaddr_in peer;
        socklen_t len=sizeof(peer);

        int newfd=accept(fd_,(struct sockaddr*)&peer, &len);
        if(newfd<0)
        {
            lg(Warning,"accept error: ",errno,strerror(errno));
            return -1;
        }
        char ipstr[64];
        inet_ntop(AF_INET,&peer.sin_addr,ipstr,sizeof(ipstr));
        *clintip=ipstr;
        *clintport=ntohs(peer.sin_port);

        return newfd;
    }
    bool Connect(std::string &ip,std::uint16_t& port)
    {
        struct sockaddr_in peer;
        memset(&peer,0,sizeof(peer));
        peer.sin_family=AF_INET;
        peer.sin_port=htons(port);
        
        int n=connect(fd_,(struct sockaddr*)&peer,sizeof(peer));
        if(n==-1)
        {
            std::cerr<<"connect to "<<ip<<":"<<port<<"errno"<<std::endl;
            return false;
        }
        return true;
        
    }
    void Close()
    {
        close(fd_);
    }
    int Fd()
    {
        return fd_;
    }
private:
    int fd_;
};